home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
atari
/
c
/
snz128s
/
src
/
snews1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-02
|
40KB
|
1,412 lines
/*
SNEWS 2.0
snews - a simple threaded news reader
Copyright (C) 1991 John McCombs, Christchurch, NEW ZEALAND
john@ahuriri.gen.nz
PO Box 2708, Christchurch, NEW ZEALAND
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 1, as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the file COPYING, which contains a copy of the GNU General
Public License.
Atari version ported by Graham Judd - gjudd@siward.demon.co.uk
*/
/*---------------------------- Source Control ------------------------------*/
/*
* $Id: snews1.c,v 1.3 1994/02/05 19:34:56 gbj Exp user $
*/
/****************************************************************************
* 20 May 92 1.2 GT ka9q mods. *
* 22 May 92 1.3 GT Set time zone. *
* 05 Jun 92 1.4 GT Nikki Locke's SPACE command. *
* 06 Jun 92 1.5 GT Invalidate freed pointers. *
* 09 Jun 92 1.6 GT Right and left cursor keys. *
* 12 Jun 92 1.7 NJL Add v_init call & change to use scr_lines. *
* Add 'q' as alternative to ESC throughout. *
* Fix memory leak when Escaping from read_thread. *
* Ensure strtok() accepts tab as well as space. *
* 17 Jul 92 1.8 GT C++ compilation. *
* Heap debugging. *
* Swap out when executing child process. *
* 16 Aug 92 1.9 MSM Snews 1.9 *
* Lock history etc. during use *
* 31 May 93 1.10 MSM Snews 2.0 *
* 18 Jun 93 1.11 MSM Heap debugging removed (using Bounds Check) *
* 10 Jul 93 1.12 MSM New commands added, help updated *
* 7 Aug 93 1.13 MSM Change command functionality to be TINish *
* MSM Add expert mode *
* MSM Add confirm exit mode *
* 26 Aug 93 1.13 MSM Colour Support clean up, Expert toggle, bugs *
* 3 Oct 92 1.14 MSM Case sensitive y/n questions made insensitive *
* old style tab action added, new config options *
* 132 col / 43 line support corrected *
* article/thread save function corrected. *
* 24 Nov 93 1.15 MSM Changed to Delta version control *
* Session setting text changes *
* 25 Nov 93 1.16 MSM Correct read list processing *
* 5 Feb 94 AT2 GBJ Ported to Atari ST *
* 2 Apr 94 1.17 MSM Add print thread support *
* abort/replace/append choice for thread save *
* 15.89 style added to smart match *
* Save full newsgroup *
* Suspend support *
*****************************************************************************/
#include <time.h>
#include <io.h>
#include <fcntl.h>
#include "defs.h"
#include "snews.h"
#include "screen.h"
#ifdef ATARI
# include <sys/types.h>
# include "st.h"
# include "fileops.h"
#else
# include "exec.h"
#endif
#include "locking.h"
#ifndef __TURBOC__
#ifndef ATARI
#include <graph.h>
#include <dos.h>
#define BLACK 0
#define LIGHTGRAY 7
unsigned long farcoreleft(void);
#endif
#endif
int xfile = FALSE;
INFO my_stuff;
#ifdef ATARI
unsigned long _STACK = 32768;
#else
unsigned _stklen = 16384;
#endif
char search_text[128];
char save_name[65];
char search_group[80];
/*------------------------------- main --------------------------------*/
void main(void)
{
ACTIVE *gp, *head;
ACTIVE *tmp_ng;
int articles, j, unread;
int done;
tzset();
fprintf(stderr, "loading config... ");
if (load_stuff()) {
v_init(my_stuff.directvideo); /* initialise bios video package */
if (mlock(my_stuff.news_dir, "history", "Snews") != 0) {
printf("snews: Unable to lock history!\n");
exit(2);
}
if (mlock(my_stuff.news_dir, my_stuff.user, "Snews") != 0) {
printf("snews: Unable to lock user %s!\n", my_stuff.user);
rmlock(my_stuff.news_dir, "history", "Snews");
exit(2);
}
textbackground(textb);
textcolor(textf);
gotoxy(1, 1);
clrscr();
gotoxy((scr_cols/2) - 23, (scr_rows/2) - 8);
printf("D E M O N I N T E R N E T S E R V I C E S");
gotoxy((scr_cols/2) - 18, (scr_rows/2) - 6);
printf("U s e n e t N e w s R e a d e r");
gotoxy((scr_cols/2) - 11, (scr_rows/2) - 4);
printf("Version %d.%02d [build %d]", rmj, rmm, rup);
gotoxy((scr_cols/2) - 20, (scr_rows/2) - 2);
printf("Based on Simple News 2.0 by John McCombs");
#ifdef ATARI
gotoxy((scr_cols/2) - 17, (scr_rows/2));
textbackground(headb);
textcolor(headf);
printf("Support: gjudd@siward.demon.co.uk");
textbackground(textb);
textcolor(textf);
#else
gotoxy((scr_cols/2) - 14, (scr_rows/2));
printf("Support: internet@demon.net");
#endif
gotoxy((scr_cols/2) - 1, (scr_rows/2) + 2);
printf("or");
gotoxy((scr_cols/2) - 26, (scr_rows/2) + 4);
printf("Type 'B' at any menu and complete the questionnaire");
gotoxy((scr_cols/2) - 31, (scr_rows/2) + 6);
printf("Source available under GNU Licence by FTP from ftp.demon.co.uk");
gotoxy(1, scr_rows - 1);
printf("loading active... ");
head = load_active_file();
add_suspend(head);
printf("loading read list... ");
load_read_list();
printf("loading history... ");
load_history_list(1);
done = FALSE;
gp = NULL;
strcpy(search_group, "demon.announce");
while (!done) {
if ((gp = select_group(head, gp)) != NULL) {
if ((read_group(gp) == EX_NEXT) && (gp->next != NULL)) {
tmp_ng = gp->next;
unread = 0;
while (tmp_ng != NULL) {
articles = (int) (tmp_ng->hi_num - tmp_ng->lo_num);
for (j=0;j<articles;j++) {
if (*((tmp_ng->read_list) + j) == FALSE)
unread++;
}
if (unread > 0)
break;
tmp_ng= tmp_ng->next;
}
if (unread > 0)
gp = tmp_ng;
else
message("-- No more articles to read --");
}
}
else
done = TRUE;
}
textbackground(textb);
textcolor(textf);
clrscr();
free_hist_list();
save_read_list();
close_active_file();
rmlock(my_stuff.news_dir, "history", "Snews");
rmlock(my_stuff.news_dir, my_stuff.user, "Snews");
}
else {
fprintf(stderr, "Couldn't find neccessary item in the .rc files\n");
}
#ifdef ATARI
printf("\033q\n");
#endif
}
/*-------------------------- find which group to read ----------------------*/
ACTIVE *select_group(ACTIVE * head, ACTIVE * current)
{
/*
* Present the list of groups, and allow him to move up and down with
* the arrow and PgUp and PgDn keys. 'h' for help
*/
ACTIVE *top; /* newsgroup at the top of the page */
ACTIVE *this_group; /* current newsgroup */
ACTIVE *tmp_ng;
int exit_code; /* why we are exiting the loop */
char sub_tmp[80];
int ch, i, j, articles, unread, ch2;
this_group = (current == NULL) ? head : current;
top = head;
exit_code = 0;
show_groups(&top, this_group, TRUE, head);
while (exit_code == 0) {
ch = getch();
switch (ch) {
case 0:
case 0xE0:
{
ch = getch();
switch (ch) {
case Fn1:
show_help(HELP_GROUP);
show_groups(&top, this_group, TRUE, head);
break;
case Fn2:
show_values();
show_groups(&top, this_group, TRUE, head);
break;
case Fn3:
change_values();
show_groups(&top, this_group, TRUE, head);
break;
case UP_ARR:
if (this_group->last != NULL)
this_group = this_group->last;
break;
case DN_ARR:
if (this_group->next != NULL)
this_group = this_group->next;
break;
case PGUP:
for (i = this_group->index - top->index;
i < PAGE_LENGTH; i++) {
if (this_group->last == NULL)
break;
this_group = this_group->last;
}
break;
case PGDN:
for (i = this_group->index - top->index;
i < PAGE_LENGTH; i++) {
if (this_group->next == NULL)
break;
this_group = this_group->next;
}
break;
case HOME:
top = this_group = head;
show_groups(&top, this_group, TRUE, head);
break;
case END:
top = this_group = head;
while (this_group->next != NULL)
this_group = this_group->next;
break;
case RT_ARR:
exit_code = EX_DONE;
break;
} /* switch (ch) */
break;
}
case '!':
textbackground(headb);
textcolor(headf);
clrscr();
#ifdef ATARI
printf("Sorry, function not supported. \n\n");
printf("Press a key to return to Snews.\n\n");
getch();
#else
printf("Type <EXIT> to return to Snews.\n\n");
system("");
#endif
textbackground(textb);
textcolor(textf);
clrscr();
show_groups(&top, this_group, TRUE, head);
break;
case 'k':
if (this_group->last != NULL)
this_group = this_group->last;
break;
case 'j':
if (this_group->next != NULL)
this_group = this_group->next;
break;
case 2: /* ^B */
case 21: /* ^U */
case 'b':
for (i = 0; i < PAGE_LENGTH; i++) {
if (this_group->last == NULL)
break;
this_group = this_group->last;
}
break;
case 4: /* ^D */
case 6: /* ^F */
case ' ':
for (i = 0; i < PAGE_LENGTH; i++) {
if (this_group->next == NULL)
break;
this_group = this_group->next;
}
break;
case 'w':
strcpy(sub_tmp, "");
if (this_group->suspend == TRUE) {
message("This group is suspende, post regardless ? (y/n ");
ch2 = getch();
ch2 = tolower(ch2);
message("");
}
else
ch2 = 'y';
if (ch2 == 'y') {
post(NULL, this_group->group, sub_tmp);
show_groups(&top, this_group, TRUE, head);
}
break;
case 'v':
#ifdef ATARI
sprintf(sub_tmp, "Demon Internet Simple News v%02d.%02d.%02d LC5 compiled %s", rmj, rmm, rup, __DATE__);
#else
#ifdef __TURBOC__
sprintf(sub_tmp, "Demon Internet Simple News v%02d.%02d.%02d BC++ compiled %s", rmj, rmm, rup, __DATE__);
#else
sprintf(sub_tmp, "Demon Internet Simple News v%02d.%02d.%02d MSVC compiled %s", rmj, rmm, rup, __DATE__);
#endif
#endif
message(sub_tmp);
getch();
show_groups(&top, this_group, TRUE, head);
break;
case 's':
case 'S':
save_group_to_disk(this_group);
message("");
break;
case 'H':
case 'h':
show_help(HELP_GROUP);
show_groups(&top, this_group, TRUE, head);
break;
case 'Z':
case 'z':
mark_group_as_unread(this_group);
show_groups(&top, this_group, TRUE, head);
break;
case 'g':
this_group = search_for_group(head, TRUE);
break;
case '/':
case '+':
case '=':
this_group = search_for_group(this_group, TRUE);
break;
case '?':
case '-':
this_group = search_for_group(this_group, FALSE);
break;
case 'M':
mail_to_someone(NULL);
show_groups(&top, this_group, TRUE, head);
break;
case 'c':
if (mark_group_as_read(this_group, TRUE) == TRUE)
show_groups(&top, this_group, TRUE, head);
else
message("");
break;
case 'C':
if (mark_group_as_read(this_group, TRUE) != TRUE) {
message("");
break;
}
show_groups(&top, this_group, TRUE, head);
/* and drop into 'N' code */
case 'N':
tmp_ng = this_group;
unread = 0;
articles = (int) (tmp_ng->hi_num - tmp_ng->lo_num);
for (j=0; j < articles; j++) {
if (*((tmp_ng->read_list) + j) == FALSE)
unread++;
}
if (unread > 0) {
break;
}
else
tmp_ng = this_group->next;
unread = 0;
while (tmp_ng != NULL) {
articles = (int) (tmp_ng->hi_num - tmp_ng->lo_num);
for (j = 0; j < articles; j++) {
if (*((tmp_ng->read_list) + j) == FALSE)
unread++;
}
if (unread > 0) {
break;
}
tmp_ng = tmp_ng->next;
}
if (unread > 0) {
this_group = tmp_ng;
}
else {
message("-- No more unread articles --");
}
break;
case TAB:
case 'n':
if (my_stuff.tab_action == TRUE) {
tmp_ng = this_group;
unread = 0;
articles = (int) (tmp_ng->hi_num - tmp_ng->lo_num);
for (j=0; j < articles; j++) {
if (*((tmp_ng->read_list) + j) == FALSE)
unread++;
}
if ((unread > 0) && (tmp_ng->suspend == FALSE)) {
exit_code = EX_DONE;
break;
}
else
tmp_ng = this_group->next;
unread = 0;
while (tmp_ng != NULL) {
articles = (int) (tmp_ng->hi_num - tmp_ng->lo_num);
for (j = 0; j < articles; j++) {
if (*((tmp_ng->read_list) + j) == FALSE)
unread++;
}
if ((unread > 0) && (tmp_ng->suspend == FALSE)) {
exit_code = EX_DONE;
break;
}
unread = 0;
tmp_ng = tmp_ng->next;
}
if ((unread > 0) && (tmp_ng->suspend == FALSE)) {
this_group = tmp_ng;
}
else {
message("-- No more articles to read --");
}
break;
}
else { /* old style action */
tmp_ng = this_group->next;
unread = 0;
while (tmp_ng != NULL) {
articles = (int) (tmp_ng->hi_num - tmp_ng->lo_num);
for (j = 0; j < articles; j++) {
if ( *((tmp_ng->read_list)+j) == FALSE)
unread++;
}
if ((unread > 0) && (tmp_ng->suspend == FALSE))
break;
unread = 0;
tmp_ng = tmp_ng->next;
}
if (unread > 0) {
this_group = tmp_ng;
} else {
message("-- No more articles to read --");
}
break;
}
case ENTER:
exit_code = EX_DONE;
break;
case ESCAPE:
case 'Q':
case 'q':
if (my_stuff.exitconfirm != 1) {
message(" EXIT - Are you sure (y/n) ? ");
ch = getch();
if (ch == 'y')
exit_code = EX_QUIT;
else
show_groups(&top, this_group, TRUE, head);
}
else {
exit_code = EX_QUIT;
}
break;
case 'B':
bug_report();
show_groups(&top, this_group, TRUE, head);
break;
};
if (exit_code == 0)
show_groups(&top, this_group, FALSE, head);
}
if (exit_code == EX_DONE)
return (this_group);
else
return (NULL);
}
/*----------------------- Search for a newsgroup --------------------------*/
ACTIVE *search_for_group(ACTIVE *this_group, int direction)
{
char pattern[128];
char prompt[80];
ACTIVE *act;
int found=FALSE;
#ifdef ATARI
ACTIVE *hit;
/*
This has been added because, as the routine stands, if the
matched group is the very last in the list, then act == NULL
and the assignment of act->last, act->next depending upon
direction causes a bus error. So, hit is set to act which will
not be NULL UNLESS the search string does not appear in ANY
group name. If hit is NULL, this_group is returned.
*/
#endif
sprintf(prompt, "Search %s for [%s] ? ", direction ? "forwards" : "backwards",
search_group);
lmessage(prompt);
gets(pattern);
if (pattern[0] == 0x1b) {
lmessage("");
return this_group;
}
if (strlen(pattern) > 0) {
strcpy(search_group, pattern);
}
else {
strcpy(pattern, search_group);
}
message ("*** searching - please wait ***");
hit = NULL;
strlwr(pattern);
if (direction) {
for (act=this_group->next;!found && act!=NULL;act=act->next) {
found = (strstr(act->group, pattern) != NULL);
#ifdef ATARI
if (found) {
hit = act;
break;
}
#endif
}
}
else {
for(act=this_group->last;!found && act!=NULL;act=act->last) {
found = (strstr(act->group, pattern) != NULL);
#ifdef ATARI
if (found) {
hit = act;
break;
}
#endif
}
}
lmessage("");
#ifdef ATARI
if (found && hit) {
#else
if (found) {
#endif
lmessage("");
#ifdef ATARI
return hit;
#else
return(direction ? act->last : act->next);
#endif
}
else {
sprintf(prompt, "*** %s not found - press any key ***", pattern);
message(prompt);
getch();
message("");
return this_group;
}
}
/*---------------------------- help screen ---------------------------------*/
void show_help(int h)
{
char *type[] = {"Newsgroup", "Thread", "Article"};
char buf[256];
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
clreol();
sprintf(buf, "%s Help (%s)\r\n", type[h], VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
clreol();
textbackground(helpb);
textcolor(helpf);
switch (h) {
case HELP_GROUP:
cprintf("\r\n\r\n");
cprintf(" LIST NEWSGROUPS CHOOSING NEWSGROUPS\r\n\r\n");
cprintf(" sUP move display up one page TAB go to next unread newsgroup\r\n");
cprintf(" sDN move display down one page ENTER read selected newsgroup\r\n");
cprintf(" Home move to top of list RIGHT read selected newsgroup\r\n");
cprintf(" End move to bottom of list\r\n");
cprintf(" UP move up one line\r\n");
cprintf(" DOWN move down one line\r\n\r\n");
cprintf(" POST ARTICLE SPECIAL ACTIONS\r\n\r\n");
cprintf(" w post article in newsgroup c mark this newsgroup as read\r\n");
cprintf(" C mark group as read and goto next\r\n");
cprintf(" z mark this newsgroup as unread\r\n");
cprintf(" F2 show user values\r\n");
cprintf(" F3 Toggle Expert Mode\r\n");
cprintf(" ESCAPE exit Snews\r\n");
cprintf(" q exit Snews\r\n");
cprintf(" v show version information\r\n");
message("-- Press any key for next page --");
getch();
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
clreol();
sprintf(buf, "%s Help (%s)\r\n", type[h], VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
clreol();
textbackground(helpb);
textcolor(helpf);
cprintf("\r\n\r\n");
cprintf(" MAIL\r\n\r\n");
cprintf(" M mail to someone\r\n\r\n");
cprintf(" SEARCHING\r\n\r\n");
cprintf(" g search for newsgroup by name\r\n");
cprintf(" + / search following for newsgroup\r\n");
cprintf(" - ? search preceeding for newsgroups\r\n\r\n");
cprintf(" MISCELLANEOUS\r\n\r\n");
cprintf(" ! shell out (NOT SUPPORTED)\r\n");
cprintf(" s save all articles in newsgroup to disk\r\n");
cprintf(" B mail a support query to DEMON\r\n");
break;
case HELP_THREAD:
cprintf("\r\n\r\n");
cprintf(" LISTING THREADS READING THREADS\r\n\r\n");
cprintf(" sUP move display up one page TAB read next unread article\r\n");
cprintf(" sDN move display down one page BACKSP read the last/prev. article\r\n");
cprintf(" Home move to top of list ENTER read the selected thread\r\n");
cprintf(" End move to bottom of list RIGHT read the selected thread\r\n");
cprintf(" UP move up one line LEFT display newsgroups\r\n");
cprintf(" DOWN move down one line q display newsgroups\r\n\r\n");
cprintf(" MARKING THREADS EXTRACT THREADS\r\n\r\n");
cprintf(" c mark as read, go to groups s save thread to disk\r\n");
cprintf(" C mark newsgroup as read S extract thread to mail \"%s\"\r\n", my_stuff.extruser);
cprintf(" K mark current thread as read in mail directory\r\n");
cprintf(" X mark all threads before\r\n");
cprintf(" current as read\r\n");
cprintf(" z mark current thread as unread\r\n");
message("-- Press any key for next page --");
getch();
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
clreol();
sprintf(buf, "%s Help (%s)\r\n", type[h], VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
clreol();
textbackground(helpb);
textcolor(helpf);
cprintf("\r\n\r\n");
cprintf(" MAIL POSTING\r\n\r\n");
cprintf(" M mail to someone w post article to newsgroup\r\n\r\n");
cprintf(" SEARCHING\r\n\r\n");
cprintf(" + search for text in following subjects\r\n");
cprintf(" / search for text in following bodies\r\n");
cprintf(" - search for text in preceeding subjects\r\n");
cprintf(" ? search for text in preceeding bodies\r\n\r\n");
cprintf(" MISCELLANEOUS\r\n\r\n");
cprintf(" F2 show user values v show version information\r\n");
cprintf(" F3 Toggle Expert Mode\r\n");
cprintf(" ! shell out (NOT SUPPORTED)\r\n");
cprintf(" B mail a support query to DEMON\r\n");
break;
case HELP_ARTICLES:
cprintf("\r\n\r\n");
cprintf(" READING ARTICLES CHOOSING ARTICLES\r\n\r\n");
cprintf(" sUP move display up one page TAB read next page / unread article\r\n");
cprintf(" sDN move display down one page ENTER read next article\r\n");
cprintf(" Home move to top of article RIGHT read next article in thread\r\n");
cprintf(" End move to bottom of article LEFT read prior article in thread\r\n");
cprintf(" UP move up one line p read prior article in thread\r\n");
cprintf(" DOWN move down one line < read first article in thread\r\n");
cprintf(" b move back one page > read last article in thread\r\n");
cprintf(" n mark this article as read\r\n");
cprintf(" and read next unread MISCELLANEOUS\r\n");
cprintf(" K mark this and remainder of\r\n");
cprintf(" thread as read ! shell out (NOT SUPPORTED)\r\n");
cprintf(" z mark this article unread\r\n");
cprintf(" d ROT13 this article\r\n");
message("-- Press any key for next page --");
getch();
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
clreol();
sprintf(buf, "%s Help (%s)\r\n", type[h], VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
clreol();
textbackground(helpb);
textcolor(helpf);
cprintf("\r\n\r\n");
cprintf(" POST ARTICLE SEND MAIL\r\n\r\n");
cprintf(" w post new article r mail reply to author\r\n");
cprintf(" f post follow-up article R mail reply to someone\r\n");
cprintf(" m mail article to someone\r\n");
cprintf(" M mail to someone\r\n\r\n");
cprintf(" SPECIAL ACTION EXTRACT ARTICLES\r\n\r\n");
cprintf(" d decode ROT-13 article s save article to file\r\n");
cprintf(" F2 show user values S extract article to mail \"%s\"\r\n", my_stuff.extruser);
cprintf(" F3 Toggle Expert Mode in mail directory\r\n");
cprintf(" B Mail a support query o print article\n\r");
cprintf(" v show version information\r\n\r\n");
cprintf(" SEARCHING\r\n\r\n");
cprintf(" + / search for text in following articles\r\n");
cprintf(" - ? search for text in preceding articles\r\n");
break;
};
message("-- Press any key to continue --");
getch();
}
/*-------------- show the values of user defined variables -------------*/
void show_values(void)
{
char buf[256];
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
#ifdef ATARI
printf("%*s", scr_cols, " ");
#else
clreol();
#endif
sprintf(buf, "Pre-set User values (%s)\r\n", VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
#ifndef ATARI
clreol();
#endif
textbackground(helpb);
textcolor(helpf);
#ifndef ATARI
cprintf("\r\n\r\n");
#endif
gotoxy(1, 4);
cprintf(" User Name: %s@%s.%s (%s)\r\n\r\n", my_stuff.user, my_stuff.my_site,
my_stuff.my_domain, my_stuff.my_name);
cprintf(" Local node name: %s\r\n", my_stuff.my_site);
cprintf(" Mail Server: %s\r\n", my_stuff.mail_server);
cprintf(" Organization: %s\r\n\r\n", my_stuff.my_organisation);
cprintf(" Signature File: %s%s\r\n", my_stuff.home, my_stuff.signature);
cprintf(" Reply To: %s\r\n\r\n", my_stuff.replyuser);
cprintf(" File Editor: %s\r\n", my_stuff.editor);
cprintf(" Edit Parameters: %s\r\n\r\n", my_stuff.edit_line);
cprintf(" News Home Directory: %s\r\n", my_stuff.news_dir);
cprintf(" Mail Directory: %s\r\n", my_stuff.mail_dir);
cprintf(" Spool Directory: %s\r\n\r\n", my_stuff.spooldir);
cprintf(" Posts saved to user: %s\r\n", my_stuff.mailuser);
cprintf(" Mail saved to user: %s\r\n", my_stuff.maillog);
cprintf(" Extracts saved to user: %s\r\n\r\n", my_stuff.extruser);
message("-- Press any key for next page --");
getch();
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
#ifdef ATARI
printf("%*s", scr_cols, " ");
#else
clreol();
#endif
sprintf(buf, "Pre-set User values (%s)\r\n", VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
#ifndef ATARI
clreol();
#endif
textbackground(helpb);
textcolor(helpf);
#ifndef ATARI
cprintf("\r\n\r\n");
#endif
gotoxy(1, 4);
cprintf(" Quoting string: \"%s\"\r\n", my_stuff.quotemark);
cprintf(" News articles mailed to: %s@%s\r\n\r\n", my_stuff.mail_id, my_stuff.mail_server);
cprintf(" Temporary file location: %s\r\n", my_stuff.temp_name);
cprintf(" Incoming news directory: %s\r\n", my_stuff.incoming_dir);
cprintf(" Mail home directory: %s\r\n", my_stuff.home);
cprintf(" ka9q nntp directory: %s\r\n", my_stuff.nntp_dir);
cprintf(" Alias name file: %s\r\n\r\n", my_stuff.alias_file);
cprintf(" Local posting enabled: %s\r\n", my_stuff.localpost ? "Yes" : "No");
cprintf(" Mark local post as read: %s\r\n\r\n", my_stuff.localread ? "Yes" : "No");
cprintf(" Prompt before exit: %s\r\n", my_stuff.exitconfirm ? "No" : "Yes");
cprintf(" Expert mode: %s\r\n", my_stuff.expert ? "Yes" : "No");
cprintf(" TAB Style: %s\r\n", my_stuff.tab_action ? "New" : "Old");
cprintf(" Quote Headers: %s\r\n", my_stuff.header_quote ? "Quoted" : "Not Quoted");
cprintf(" Quote Footers: %s\r\n", my_stuff.footer_quote ? "Quoted" : "Not Quoted");
// cprintf(" New Threads Only: %s\r\n", my_stuff.show_unread ? "No" : "Yes");
cprintf(" Subject Match Length: %d characters\r\n", my_stuff.match_len);
message("-- Press any key to continue --");
getch();
}
/*------------- Change selected config values for the session -------------*/
void change_values()
{
int ch;
char buf[256];
textbackground(helpb);
textcolor(helpf);
clrscr();
textbackground(headb);
textcolor(headf);
#ifdef ATARI
printf("%*s", scr_cols, " ");
#else
clreol();
#endif
sprintf(buf, "Settings for this session (%s)\r\n", VERSION);
gotoxy((scr_cols/2) - (strlen(buf)/2), 1);
cprintf(buf);
#ifndef ATARI
clreol();
#endif
textbackground(helpb);
textcolor(helpf);
#ifndef ATARI
cprintf("\r\n\r\n");
#endif
do
{
gotoxy(5, 6);
cprintf("(E)xpert mode: %s", my_stuff.expert ? "On " : "Off");
gotoxy(5, 8);
cprintf("(T)ab mode: %s", my_stuff.tab_action ? "New" : "Old");
gotoxy(5, 10);
cprintf("(H)eader Quoting: %s", my_stuff.header_quote ? "On " : "Off");
gotoxy(5, 12);
cprintf("(F)ooter Quoting: %s", my_stuff.footer_quote ? "On " : "Off");
// gotoxy(5, 14);
// cprintf("(S)how Read: %s", my_stuff.show_unread ? "Off" : "On ");
message("Enter value to toggle, ESC to exit (E/T/H/F) ");
textbackground(helpb);
textcolor(helpf);
ch = getch();
ch = tolower(ch);
if (ch == 'q')
ch = ESCAPE;
switch (ch) {
case 'e':
if (my_stuff.expert == TRUE)
my_stuff.expert = FALSE;
else
my_stuff.expert = TRUE;
break;
case 't':
if (my_stuff.tab_action == TRUE)
my_stuff.tab_action = FALSE;
else
my_stuff.tab_action = TRUE;
break;
case 'h':
if (my_stuff.header_quote == TRUE)
my_stuff.header_quote = FALSE;
else
my_stuff.header_quote = TRUE;
break;
case 'f':
if (my_stuff.footer_quote == TRUE)
my_stuff.footer_quote = FALSE;
else
my_stuff.footer_quote = TRUE;
break;
// case 's':
// if (my_stuff.show_unread == TRUE)
// my_stuff.show_unread = FALSE;
// else
// my_stuff.show_unread = TRUE;
// break;
}
}
while (ch != ESCAPE);
lmessage("");
}
/*-------------------- show the list of active groups -----------------------*/
void show_groups(ACTIVE ** top, ACTIVE * this_group, int force, ACTIVE *head)
{
/*
* This routine takes 'top', a pointer to the first line on the screen
* and 'this_group' a pointer to where we want to be, and updates the
* screen. A marker to this_group is maintained, and the screen is
* repainted, where necessary
*/
static last_y;
static last_index;
int i, ur;
ACTIVE *that;
char buf[80], lbrack, rbrack;
/*
* If 'this_group' is above the 'top' or it is more than a screen
* length below, or 'this_group and 'top' are both zero, ie first
* time repaint the screen
*/
if (force ||
((*top)->index > this_group->index) ||
(this_group->index - (*top)->index) > PAGE_LENGTH - 1) {
clrscr();
textbackground(headb);
textcolor(headf);
#ifdef ATARI
for (i=0; i < 2; i++)
printf("%*s", scr_cols, " ");
#else
clreol();
#endif
gotoxy((scr_cols/2) - 8, 1);
cprintf("Select Newsgroup\r\n");
#ifndef ATARI
clreol();
#endif
gotoxy(scr_cols - 20, 2);
cprintf("Group %3d of %3d\r\n", last_index+1, head->groups);
#ifndef ATARI
clreol();
#endif
textbackground(textb);
textcolor(textf);
/* now adjust the top */
*top = this_group;
for (i = 0; i < PAGE_LENGTH / 2; i++) {
if ((*top)->last == NULL)
break;
*top = (*top)->last;
}
that = *top;
for (i = 0; i < PAGE_LENGTH; i++) {
ur = count_unread_in_group(that);
gotoxy(8, i+5);
if (that->suspend == TRUE) {
lbrack = '[';
rbrack = ']';
}
else
lbrack = rbrack = ' ';
if (ur > 0) {
printf("%4d %4ld %c%s%c ", ur, that->hi_num - that->lo_num,
lbrack, that->group, rbrack);
}
else
printf(" %4ld %c%s%c", that->hi_num - that->lo_num,
lbrack, that->group, rbrack);
that = that->next;
if (that == NULL)
break;
}
last_y = this_group->index - (*top)->index;
gotoxy(4, last_y + PAGE_HEADER+1);
putch('-'); putch('>');
last_index = this_group->index;
}
else {
gotoxy(4, last_y + PAGE_HEADER+1);
putch(' '); putch(' '); /* deliberate putch for HBJ */
last_y += (this_group->index - last_index);
gotoxy(4, last_y + PAGE_HEADER+1);
putch('-'); putch('>');
last_index = this_group->index;
}
gotoxy(scr_cols - 20,2);
textbackground(headb); textcolor(headf);
cprintf("Group %3d of %3d\r\n", last_index+1, head->groups);
textbackground(textb); textcolor(textf);
sprintf(buf, "ESC=quit TAB=next unread group ENTER=read group F1 or 'h'=help [%ldk]",
farcoreleft() / 1024);
command(buf);
}
/*--------------------------- process message -------------------------------*/
int read_group(ACTIVE * gp)
{
/*
* We now have newsgroup. Access the directory and try to read
* the newsgroup articles, extracting the headers.
*/
ARTICLE *start;
int exit_code;
#ifdef ATARI
// int i;
#endif
if (gp->lo_num < gp->hi_num) {
clrscr();
textbackground(headb);
textcolor(headf);
#ifdef ATARI
// for (i=0; i < 3; i++)
// printf("%*s", scr_cols, " ");
#else
clreol();
gotoxy((scr_cols/2) - 7, 1);
printf("Select Thread\n");
clreol();
printf("Group: %s ", gp->group);
clreol();
#endif
textbackground(textb);
textcolor(textf);
start = get_headers(gp);
exit_code = select_thread(gp, start);
free_header(start);
start = NULL;
}
return (exit_code);
}
/*------------------------- show the list of threads -----------------------*/
void show_threads(ACTIVE * gp, ARTICLE ** top, ARTICLE * this_group,
int force, ARTICLE *head)
{
/*
* This routine takes 'top', a pointer to the first line on the screen
* and 'this_group' a pointer to where we want to be, and updates the
* screen. A maker to this_group is maintained, and the screen is
* repainted, where necessary
*/
static last_y;
static last_index;
int i;
ARTICLE *that;
int unread;
int ur;
char buf[80];
/*
* If 'this_group' is above the 'top' or it is more than a screen
* length below, or'this_group and 'top' are both zero, ie first
* time repaint the screen
*/
if (force ||
((*top)->index > this_group->index) ||
(this_group->index - (*top)->index) > PAGE_LENGTH - 1) {
for(that=head, ur=0;that;that=that->next)
ur += count_unread_in_thread(gp, that);
clrscr();
textbackground(headb);
textcolor(headf);
#ifdef ATARI
for (i=0; i < 3; i++)
printf("%*s", scr_cols, " ");
#else
clreol();
#endif
gotoxy((scr_cols/2) - 7, 1);
cprintf("Select Thread\r\n");
#ifndef ATARI
clreol();
#endif
cprintf("Group: %s", gp->group);
gotoxy(scr_cols - 25, 2);
cprintf("%4ld Articles, %4d unread\r\n", gp->hi_num - gp->lo_num, ur);
#ifndef ATARI
clreol();
#endif
gotoxy(scr_cols - 25, 3);
cprintf("Thread %4d of %4d", last_index+1, gp->threads);
textbackground(textb);
textcolor(textf);
/* now adjust the top */
*top = this_group;
for (i = 0; i < PAGE_LENGTH / 2; i++) {
if ((*top)->last == NULL)
break;
*top = (*top)->last;
}
that = *top;
for (i = 0; i < PAGE_LENGTH; i++) {
unread = count_unread_in_thread(gp, that);
gotoxy(8, i + 5);
if (unread > 0)
printf("%4d %4d %s", unread, that->num_articles, that->header);
else
printf(" %4d %s", that->num_articles, that->header);
that = that->next;
if (that == NULL)
break;
}
last_y = this_group->index - (*top)->index;
gotoxy(4, last_y + PAGE_HEADER+1);
putch('-'); putch('>');
last_index = this_group->index;
}
else {
gotoxy(4, last_y + PAGE_HEADER+1);
putch(' '); putch(' '); /* deliberate for HBJ */
last_y += (this_group->index - last_index);
gotoxy(4, last_y + PAGE_HEADER+1);
putch('-'); putch('>');
last_index = this_group->index;
}
gotoxy(scr_cols - 25, 3);
textbackground(headb); textcolor(headf);
cprintf("Thread %4d of %4d", last_index+1, gp->threads);
textbackground(textb); textcolor(textf);
sprintf(buf, "ESC=select group TAB=next unread ENTER=next article F1 or 'h'=help [%ldk]",
farcoreleft() / 1024);
command(buf);
}
/*-------------------------- search through threads ------------------------*/
ARTICLE *search_thread(ACTIVE *gp, ARTICLE *head, int search_body, int direction)
{
int found = 0, irq = FALSE;
ARTICLE *this_art;
ART_ID *art;
TEXT *tx;
LINES *text;
char *fn;
char prompt[128], pattern[128];
if (head == NULL)
return head;
sprintf(prompt, "Search %s %s for ? [%s] ",
search_body ? "articles" : "subjects",
direction ? "forwards" : "backwards", search_text);
lmessage(prompt);
gets(pattern);
if (pattern[0] == 0x1b)
return 0;
if (strlen(pattern) > 0)
strcpy(search_text, pattern);
else
strcpy(pattern, search_text);
strlwr(pattern);
if (search_body) {
message("** searching - please wait (press <ESC> to abort) ***");
if (direction) {
for (this_art=head; this_art!=NULL; this_art=this_art->next) {
/* for each article */
for (art=this_art->art_num; art!=NULL; art=art->next_art) {
fn = make_news_group_name(gp->group);
tx = load_article(fn, art->art_off, FALSE);
for (text=tx->start; !found && text!=NULL; text=text->next) {
strlwr(text->data);
found = (strstr(text->data, pattern) != NULL);
}
free_article(tx);
if (kbhit())
irq = (getch() == 27);
if (found || irq)
break;
}
if (found || irq)
break;
}
}
else {
for (this_art=head->last; this_art!=NULL; this_art=this_art->last) {
/* for each article */
for (art=this_art->art_num; art!=NULL; art=art->next_art) {
fn = make_news_group_name(gp->group);
tx = load_article(fn, art->art_off, FALSE);
for (text=tx->start; !found && text!=NULL; text=text->next) {
strlwr(text->data);
found = (strstr(text->data, pattern) != NULL);
}
free_article(tx);
if (kbhit())
irq = (getch() == 27);
if (found || irq)
break;
}
if (found || irq)
break;
}
}
}
else {
if (direction) {
for (this_art=head; this_art!=NULL; this_art=this_art->next) {
strcpy(prompt, this_art->header);
strlwr(prompt);
found = (strstr(prompt, pattern) != NULL);
if (found)
break;
}
}
else {
for (this_art=head->last; this_art!=NULL; this_art=this_art->last) {
strcpy(prompt, this_art->header);
strlwr(prompt);
found = (strstr(prompt, pattern) != NULL);
if (found)
break;
}
}
}
if (!found && !irq) {
sprintf(prompt, "*** '%s' not found - press any key ***", pattern);
message(prompt);
getch();
}
return found ? this_art : head;
}